package de.tudarmstadt.fgbs.cafe.structure;

import java.io.Serializable;

/**
 * Class, which represents a waypoint (ger.: Bahnhof) in the timetable
 * 
 * @author Christian Schlehuber
 * @version 0.1
 * 
 */

public class Wegpunkt implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 3693888151129861424L;

    // Bahnhof, which is associated with the Wegpunkt
    private Bahnhof bahnhof;
    // arrival time at this Wegpunkt
    private String ankunft;
    // departure time at this Wegpunkt
    private String abfahrt;
    // defines, where the train should stop
    private String regelgleis = "";
    // will the train change directions here
    private boolean wende = false;
    // or will it simply pass without a halt
    private boolean durchfahrt = false;
    // how long will the train stay
    private int aufenthalt;

    /**
     * Empty Constructor
     */
    public Wegpunkt() {

    }

    public Wegpunkt(Wegpunkt clone) {
	this.abfahrt = clone.getAbfahrt();
	this.ankunft = clone.getAnkunft();
	this.aufenthalt = clone.getAufenthalt();
	this.bahnhof = clone.getBahnhof();
	this.durchfahrt = clone.isDurchfahrt();
	this.regelgleis = clone.getRegelgleis();
	this.wende = clone.isWende();
    }

    /**
     * Constructor for the waypoint
     * 
     * @param bhf
     *            the associated Bahnhof for the waypoint
     * @param an
     *            String containing the arrival time at the waypoint
     * @param ab
     *            String containing the departure time at the waypoint
     * @param gleis
     *            String containing the regular track
     * @param wende
     *            boolean which determines, if the train should change direction
     * @param durch
     *            boolean which indicates, if the train should only pass the
     *            station
     * @param aufenthalt
     *            int determining the time to stay in seconds
     */
    public Wegpunkt(Bahnhof bhf, String an, String ab, String gleis,
	    boolean wende, boolean durch, int aufenthalt) {
	this.bahnhof = bhf;
	this.ankunft = an;
	this.abfahrt = ab;
	this.regelgleis = gleis;
	this.wende = wende;
	this.durchfahrt = durch;
	if (aufenthalt == -1)
	    this.aufenthalt = calculateAufenthalt(an, ab);
	else
	    this.aufenthalt = aufenthalt;
    }

    /**
     * Constructor for the waypoint (the time to stay is automatically
     * calculated)
     * 
     * @param bhf
     *            the associated Bahnhof for the waypoint
     * @param an
     *            String containing the arrival time at the waypoint
     * @param ab
     *            String containing the departure time at the waypoint
     * @param gleis
     *            String containing the regular track
     * @param wende
     *            boolean which determines, if the train should change direction
     * @param durch
     *            boolean which indicates, if the train should only pass the
     *            station
     */
    public Wegpunkt(Bahnhof bhf, String an, String ab, String gleis,
	    boolean wende, boolean durch) {
	this(bhf, an, ab, gleis, wende, durch, -1);
    }

    private int calculateAufenthalt(String an, String ab) {
	return 30;
    }

    /**
     * Method for building an export string for this object
     * 
     * @return String containing the FPL conform representation of this object
     */
    public String exportForFPL() {
	StringBuffer ausgabe = new StringBuffer();
	ausgabe.append(bahnhof.getKurzbez() + "\t");
	ausgabe.append(ankunft + "\t");
	ausgabe.append(abfahrt + "\t");
	if (durchfahrt)
	    ausgabe.append("D");
	if (wende)
	    ausgabe.append("W");
	ausgabe.append("\t");
	if (regelgleis == null)
	    regelgleis = "";
	ausgabe.append(regelgleis + "\t");
	ausgabe.append(bahnhof.getGleiseAsString() + "\t");
	ausgabe.append("\t");
	if (!durchfahrt)
	    ausgabe.append(aufenthalt);
	return ausgabe.toString();
    }

    /**
     * @return the bahnhof
     */
    public Bahnhof getBahnhof() {
	return bahnhof;
    }

    /**
     * @param bahnhof
     *            the bahnhof to set
     */
    public void setBahnhof(Bahnhof bahnhof) {
	this.bahnhof = bahnhof;
    }

    /**
     * @return the ankunft
     */
    public String getAnkunft() {
	return ankunft;
    }

    public int getAnkunftTS() {
	return timeStringToInt(ankunft);
    }

    /**
     * @param ankunft
     *            the ankunft to set
     */
    public void setAnkunft(String ankunft) {
	this.ankunft = ankunft;
    }

    /**
     * @return the abfahrt
     */
    public String getAbfahrt() {
	return abfahrt;
    }

    public int getAbfahrtTS() {
	return timeStringToInt(abfahrt);
    }

    /**
     * @param abfahrt
     *            the abfahrt to set
     */
    public void setAbfahrt(String abfahrt) {
	this.abfahrt = abfahrt;
    }

    /**
     * @return the regelgleis
     */
    public String getRegelgleis() {
	return regelgleis;
    }

    /**
     * @param regelgleis
     *            the regelgleis to set
     */
    public void setRegelgleis(String regelgleis) {
	this.regelgleis = regelgleis;
    }

    /**
     * @return the wende
     */
    public boolean isWende() {
	return wende;
    }

    /**
     * @param wende
     *            the wende to set
     */
    public void setWende(boolean wende) {
	this.wende = wende;
    }

    /**
     * @return the durchfahrt
     */
    public boolean isDurchfahrt() {
	return durchfahrt;
    }

    /**
     * @param durchfahrt
     *            the durchfahrt to set
     */
    public void setDurchfahrt(boolean durchfahrt) {
	this.durchfahrt = durchfahrt;
    }

    /**
     * @return the aufenthalt
     */
    public int getAufenthalt() {
	return aufenthalt;
    }

    /**
     * @param aufenthalt
     *            the aufenthalt to set in seconds
     */
    public void setAufenthalt(int aufenthalt) {
	this.aufenthalt = aufenthalt;
    }

    /**
     * Method for modifying the abfahrt time at this Wegpunkt
     * 
     * @param minutes
     *            int which determnines, how many minutes have to be added to
     *            the current abfahrt
     */
    public void modifyAbfahrt(int minutes) {
	String newAbfahrt = this.changeStringTime(this.abfahrt, minutes);
	this.abfahrt = newAbfahrt;
    }

    /**
     * Method for modifying the ankunft time at this Wegpunkt
     * 
     * @param minutes
     *            int which determines, how many minutes have to be added to the
     *            current ankunft
     */
    public void modifyAnkunft(int minutes) {
	String newAnkunft = this.changeStringTime(this.ankunft, minutes);
	this.ankunft = newAnkunft;
    }

    /**
     * Method for determining if modification of ankunft or abfahrt at this
     * Wegpunkt by the given amount of minutes is possible or if it would
     * collide with related points
     * 
     * @param minutes
     *            int which determines, how many minutes have to be added
     * @param isAbfahrt
     *            boolean true = abfahrt should be modified; false = ankunft
     *            should be mod
     * @return true if modification is possible
     */
    public boolean timeModificationPossible(int minutes, boolean isAbfahrt) {
	if (isAbfahrt) {
	    String newAbfahrt = this.changeStringTime(this.abfahrt, minutes);
	    if (compareStringTime(this.ankunft, newAbfahrt) > 0)
		return false;
	    else
		return true;
	} else {
	    String newAnkunft = this.changeStringTime(this.ankunft, minutes);
	    if (compareStringTime(this.abfahrt, newAnkunft) < 0)
		return false;
	    else
		return true;
	}
    }

    /**
     * 
     * @param time1
     * @param time2
     * @return 0 if equal; 1 if t1 > t2; -1 if t1 < t2
     */
    public int compareStringTime(String time1, String time2) {
	String[] parts1 = time1.split(":");
	int ts1 = Integer.parseInt(parts1[0]) * 60
		+ Integer.parseInt(parts1[1]);
	String[] parts2 = time2.split(":");
	int ts2 = Integer.parseInt(parts2[0]) * 60
		+ Integer.parseInt(parts2[1]);
	if (ts1 == ts2)
	    return 0;
	else if (ts1 > ts2)
	    return 1;
	else
	    return -1;
    }

    public String changeStringTime(String time, int amount) {
	String[] parts = time.split(":");
	int ts = Integer.parseInt(parts[0]) * 60 + Integer.parseInt(parts[1]);
	ts += amount;
	int[] resultParts = new int[2];
	resultParts[0] = ts / 60;
	resultParts[1] = ts % 60;
	String add1 = "", add2 = "";
	if (resultParts[0] < 10)
	    add1 = "0";
	if (resultParts[1] < 10)
	    add2 = "0";
	return add1 + resultParts[0] + ":" + add2 + resultParts[1];
    }

    private int timeStringToInt(String timeString) {
	int timeStamp = 0;
	if (timeString != null) {
	    String[] parts = timeString.split(":");
	    if (parts.length == 2) {
		timeStamp += Integer.parseInt(parts[0]) * 60
			+ Integer.parseInt(parts[1]);
		return timeStamp;
	    }
	}
	return -1;
    }

    @Override
    public String toString() {
	return "Bahnhof: " + bahnhof.getKurzbez() + "(An: " + ankunft
		+ " - Ab: " + abfahrt + " - min: " + aufenthalt + ") - Gleis: "
		+ regelgleis;
    }
}
